package util;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;

/**
 * modbus4j写入数据
 */
public class Modbus4jWriteUtils {

    /**
     * 工厂
     */
    static ModbusFactory modbusFactory;

    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }

    /**
     * 获取tcpMaster
     */
    public static ModbusMaster getMaster() throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost("192.168.2.188");
        params.setPort(502);
        ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false);
        tcpMaster.init();
        return tcpMaster;
    }

    /**
     * [01 Coil Status(0x)]写一个function ID = 5
     */
    public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue) throws ModbusInitException, ModbusTransportException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * [01 Coil Status(0x)]写多个function ID = 5
     */
    public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata) throws ModbusInitException, ModbusTransportException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
        // 发送请求并获取响应对象
        WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * [03 Holding Register(4x)]写一个 function ID = 6
     */
    public static boolean writeRegister(int slaveId, int writeOffset, int writeValue) throws ModbusInitException, ModbusTransportException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * [03 Holding Register(4x)]写多个 function ID = 6
     */
    public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata) throws ModbusInitException, ModbusTransportException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
        // 发送请求并获取响应对象
        WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * 写入数字类型的模拟量（如：写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long）
     */
    public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws ModbusInitException, ErrorResponseException, ModbusTransportException {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
        tcpMaster.setValue(locator, value);
    }

    public static void main(String[] args) {
        try {
            // 测试01
//            writeCoil(1, 9, true);
//            writeCoil(1, 10, true);
//            writeCoil(1, 11, true);
            // 测试02
//            writeCoils(1, 0, new boolean[] {true, false, true});
            // 测试03
//            writeRegister(1, 0, 2);
            // 测试04
//            writeRegisters(1, 0, new short[]{-3, 3, 9});
            // 写浮点数
            writeHoldingRegister(1, 0, 10.1f, DataType.FOUR_BYTE_FLOAT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
